# @Version        : 1.0
# @Update Time    : 2024/12/9 22:36
# @File           : demo_env_middleware.py
# @IDE            : PyCharm
# @Desc           : 演示环境中间件，用于限制演示环境下的操作权限
from typing import Optional
from fastapi import Request, Response
from fastapi.responses import ORJSONResponse
from starlette.middleware.base import BaseHTTPMiddleware, RequestResponseEndpoint
from src.config import settings


class DemoEnvMiddleware(BaseHTTPMiddleware):
    """演示环境中间件

    用于限制演示环境下的操作权限，只允许白名单中的路径进行非GET操作，
    黑名单中的路径完全禁止操作。
    """

    def _is_allowed_path(self, path: str) -> bool:
        """检查路径是否允许访问

        Args:
            path: 请求路径

        Returns:
            bool: 是否允许访问
        """
        # 黑名单路径直接拒绝
        if path in settings.demo.DEMO_BLACK_LIST_PATH:
            return False
        # 白名单路径允许访问
        if path in settings.demo.DEMO_WHITE_LIST_PATH:
            return True
        # 其他路径拒绝访问
        return False

    def _create_error_response(
        self, message: str = "演示环境，禁止操作"
    ) -> ORJSONResponse:
        """创建错误响应

        Args:
            message: 错误消息

        Returns:
            ORJSONResponse: 错误响应
        """
        return ORJSONResponse(content={"msg": message, "code": 400, "data": None})

    async def dispatch(
        self, request: Request, call_next: RequestResponseEndpoint
    ) -> Response:
        """处理请求

        Args:
            request: 请求对象
            call_next: 下一个处理函数

        Returns:
            Response: 响应对象
        """
        # 非演示环境直接放行
        if not settings.demo.DEMO_ENV:
            return await call_next(request)

        # GET请求直接放行
        if request.method == "GET":
            return await call_next(request)

        # 检查路径权限
        path = request.scope.get("path", "")
        if not self._is_allowed_path(path):
            return self._create_error_response()

        return await call_next(request)
